<template>
  <div>
    <a-spin :spinning="this.formLoading" tip="正在合并数据请稍后...">
      <a-row>
        <a-col :span="4" style="background-color: white;padding: 5px;height: 95vh;">
          <a-tabs v-model:activeKey="leftTabKey">
            <a-tab-pane key="layout" tab="布局组件">
              <a-row>
                <a-col v-for="field in layoutComponentsArr" class="" style="padding:2px;" :span="24">
                  <div draggable="true"
                       @mousedown="onMousedown($event, field)"
                       @dragstart="onDragstart($event, field)"
                       @dragend="onDragEnd($event)" class="field_title field_components"
                       style="width: 100%;height: 100%;border: 1px dashed #18aeff;">
                    <component :is="field.icon"/>
                    {{ field.name }}
                  </div>
                </a-col>
              </a-row>
            </a-tab-pane>
            <a-tab-pane key="form" tab="表单组件">
              <a-row>
                <a-col v-for="field in fieldComponentsArr" class="" style="padding:2px;" :span="12">
                  <div draggable="true"
                       @mousedown="onMousedown($event, field)"
                       @dragstart="onDragstart($event, field)"
                       @dragend="onDragEnd($event)" class="field_title field_components"
                       style="width: 100%;height: 100%;border: 1px dashed #bdbdbd;">
                    <component :is="field.icon"/>
                    {{ field.name }}
                  </div>
                </a-col>
              </a-row>
            </a-tab-pane>
            <a-tab-pane key="field" tab="字段信息">
              <a-row>
                <a-col v-for="field in this.formData.formBean.fieldMap" class="" style="padding:2px;" :span="24">
                  <div draggable="true"
                       @mousedown="onMousedown($event, field)"
                       @dragstart="onDragstart($event, field)"
                       @dragend="onDragEnd($event)" class="field_title field_components"
                       style="width: 100%;height: 100%;border: 1px dashed #bdbdbd;">
                    {{ field.fieldName + '  [' + field.dbFieldName + ']' }}
                  </div>
                </a-col>
              </a-row>
            </a-tab-pane>
          </a-tabs>
        </a-col>
        <a-col :span="16" style="height: 90vh;padding: 5px;" @dragover.prevent @drop="onDrop">
          <div style="background-color: white;height: 100%;">
            <div style="margin-left: 7px;padding: 5px;"
                 v-for="(viewItem,index1) in this.formData.formBean.viewBean.viewItemList">
              <div v-if="viewItem.showType === showType.mainTable">
                <a-divider orientation="left" orientation-margin="0px">
                  <a-tag color="#2db7f5">
                    <a-input v-model:value="viewItem.refObj.name" :bordered="false" size="small" style="width: 8vh"
                             placeholder="表格名称"></a-input>
                  </a-tag>
                </a-divider>
                <table
                    style="width: 100%;table-layout: fixed">
                  <tbody>
                  <tr v-for="(item,lineNum) in viewItem.refObj.line">
                    <td v-for="(element,rowNum) in viewItem.refObj.row" @dragover.prevent @drop="onDropMainTable"
                        :id="this.getTableColId(viewItem,lineNum,rowNum)" :p_table_id="viewItem.refObj.id"
                        style="border: 1px solid rgba(199,197,197,0.24);height: 55px;">
                      <def-field v-if="this.getBindData(viewItem,lineNum,rowNum)" :ext="{disabled: true}"
                                 :formField=this.getBindData(viewItem,lineNum,rowNum)
                                 @click="selectField(this.getBindData(viewItem,lineNum,rowNum)?.dbFieldName)"></def-field>
                    </td>
                  </tr>
                  </tbody>
                </table>
              </div>

              <def-field v-if="viewItem.showType === showType.field" :formField=this.getBindData(viewItem)
                         :ext="{disabled: true}"
                         @click="selectField(viewItem.refObj.id)"></def-field>
            </div>
          </div>
          <sapn v-for="(view,index1) in this.formData.formBean.viewList">
            <a-button> {{ view.viewName }}</a-button>
          </sapn>
        </a-col>
        <a-col :span="4" style="background-color: white;padding: 5px">
          <a-tabs v-model:activeKey="activeKey">
            <a-tab-pane key="1" tab="表单属性">
              <a-form :label-col="labelCol" :wrapper-col="wrapperCol">
                <a-form-item label="表单名称">
                  <a-input v-model:value="this.formData.formBean.formName"/>
                </a-form-item>
                <a-form-item label="数据库表名">
                  <a-input disabled v-model:value="this.formData.formBean.mainTableBean.dbTableName"/>
                </a-form-item>
              </a-form>
            </a-tab-pane>
            <a-tab-pane key="2" tab="组件属性" force-render>
              <a-form :label-col="labelCol" :wrapper-col="wrapperCol">
                <a-form-item label="Label">
                  <a-input v-model:value="this.formData.formBean.selectFormField.fieldName"/>
                </a-form-item>
                <a-form-item label="字段名">
                  <a-input disabled v-model:value="this.formData.formBean.selectFormField.dbFieldName"/>
                </a-form-item>
                <a-form-item label="字段类型">
                  <a-input v-model:value="this.formData.formBean.selectFormField.fieldDataType"/>
                </a-form-item>
                <a-form-item label="字段长度">
                  <a-input v-model:value="this.formData.formBean.selectFormField.fieldLength"/>
                </a-form-item>
                <a-form-item label="宽度">
                  <a-input v-model:value="this.formData.formBean.selectFormField.width"/>
                </a-form-item>
                <a-form-item label="栅格宽度">
                  <a-input v-model:value="this.formData.formBean.selectFormField.span"/>
                </a-form-item>
              </a-form>
            </a-tab-pane>
          </a-tabs>
        </a-col>
      </a-row>
    </a-spin>

    <div>
      <a-modal
          v-model:visible="mainTableInitConfirmShow"
          :title="mainTableInitConfirmData.name"
          ok-text="确认"
          cancel-text="取消"
          @ok="generateMainTableView"
      >
        <a-row>
          <a-col :span="12">
            <a-form-item name="line" label="行数">
              <a-input-number id="inputLine" v-model:value="mainTableInitConfirmData.line" :min="1" :max="10"/>
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="row" label="列数">
              <a-input-number id="inputRow" v-model:value="mainTableInitConfirmData.row" :min="1" :max="10"/>
            </a-form-item>
          </a-col>
        </a-row>
      </a-modal>
    </div>
  </div>
</template>

<script>
import draggable from "vuedraggable";
import {DeleteOutlined} from "@ant-design/icons-vue";
import {reactive, ref, toRefs} from "vue";
import {AppFormDesignApi} from "@/components/home/lowCode/appDef/js/AppFormDesignApi";
import DefField from "@/components/home/lowCode/appDef/form/DefField";
import {ContextApi} from "@/components/js/ContextApi";

let idGlobal = 8;
let onDropSuccess = true;
const showType = {
  field: 'field', mainTable: 'mainTable'
}

export default {
  name: "defForm",
  components: {
    DefField,
    draggable,
    DeleteOutlined,
  },
  setup() {
    let formFieldIndex = 0;
    let formData = reactive({
      formBean: {
        id: '',
        appId: '',
        formName: '',
        fieldIndex: 0,
        tableIndex: 0,
        selectFormField: {},
        mainTableBean: {
          id: '',
          dbTableName: '',
          fieldList: []
        },
        fieldMap: {
          // '168f204da60d488890d0909c0d56f7b7': {
          //   id: "168f204da60d488890d0909c0d56f7b7",
          //   fieldName: "输入框",
          //   dbFieldName: "field5ne9l1",
          //   fieldDataType: "text",
          //   fieldLength: null,
          //   width: 80,
          //   scale: null,
          //   dbFieldDataType: "varchar",
          //   delete: false,
          //   sortIndex: null
          // },
          // '123': {
          //   id: "123",
          //   fieldName: "输入框",
          //   dbFieldName: "field5ne9l1",
          //   fieldDataType: "text",
          //   fieldLength: null,
          //   width: 80,
          //   scale: null,
          //   dbFieldDataType: "varchar",
          //   delete: false,
          //   sortIndex: null
          // },
        },
        currentInfo: {currentViewId: "1"},
        viewList: [{id: '123', viewName: '视图1'}],
        viewBean: {
          fieldBind: {}, // TdId: fieldId
          viewItemList: [
            {
              showType: showType.field, // 字段
              refObj: {
                "id": "field0001", // 字段数据库名称
              }
            },
            {
              showType: showType.mainTable,
              refObj: {
                id: '123',
                name: '表格1',
                line: 3,
                row: 3,
                tableContent: {
                  tab123_line1_row1: 'field0001'
                }

              }
            }
          ]
        }
      },
    });
    let mainTableInitConfirmData = reactive({
      id: '', name: '表格布局', line: 3, row: 3, componentType: showType.mainTable,
    });
    const data = reactive({
      fieldComponentsArr: [
        {id: 1, componentType: showType.field, name: '输入框', type: "text", dbType: "varchar", icon: 'form-outlined'},
        {
          id: 2,
          componentType: showType.field,
          name: '计数器',
          type: "counter",
          dbType: "int",
          icon: 'ordered-list-outlined'
        },
        {
          id: 3,
          componentType: showType.field,
          name: '单选框',
          type: "radio",
          dbType: "int",
          icon: 'check-circle-outlined'
        },
        {
          id: 4,
          componentType: showType.field,
          name: '日期选择',
          type: "date",
          dbType: "date",
          icon: 'clock-circle-outlined'
        },
        {id: 4, componentType: showType.field, name: '文件上传', type: "file", dbType: "file", icon: 'upload-outlined'},
      ],
      layoutComponentsArr: [
        {id: '', name: '表格布局', line: 3, row: 3, componentType: showType.mainTable,},
      ],
    });

    const formLoading = ref(false);
    return {
      mainTableInitConfirmData,
      mainTableInitConfirmShow: ref(false),
      showType,
      dropList: [],
      formLoading,
      ...toRefs(data),
      labelCol: {
        span: 6,
      },
      wrapperCol: {
        span: 16,
      },
      formFieldIndex,
      formData,
      activeKey: ref('1'),
      leftTabKey: ref('layout'),
    }
  },
  created() {
    this.formData.formBean.id = this.$route.query.formId;
    this.loadFormDef();
  },
  methods: {
    /**
     * 获取视图绑定的字段信息
     *
     * @param viewItem
     * @param lineNum
     * @param rowNum
     * @returns {{}}
     */
    getBindData: function (viewItem, lineNum, rowNum) {
      let fieldData = {};
      if (viewItem.showType === showType.field) {
        fieldData = this.formData.formBean.fieldMap[viewItem.refObj.id];
      } else if (viewItem.showType === showType.mainTable) {
        if (viewItem && viewItem.refObj) {
          let dbFieName = viewItem.refObj.tableContent[this.getTableColId(viewItem, lineNum, rowNum)];
          fieldData = this.formData.formBean.fieldMap[dbFieName];
        }
      }
      return fieldData;
    },
    onMousedown(event, item) {
      console.log('mousedown鼠标按下', event, item);
      // 设置图像src为svg代码, 也可以是本地方路径(用require引入)
      // this.img.src = "data:image/svg+xml,%3Csvg width='100' height='40' viewBox='0 0 100 40' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100' height='40' rx='8' fill='%230273CF'/%3E%3Cpath d='M27.496 16.936v3.304H22.96v.938h4.536v3.752h-5.698v.994h12.418v-.994h-5.698v-3.752h4.536v-.938h-4.536v-3.304h5.208v-.994h-5.768l.546-.21c-.196-.672-.462-1.4-.812-2.198l-.98.266c.336.686.63 1.4.868 2.142h-5.292v.994h5.208zm9.016-2.814v.91h4.13v1.246H37.38v3.528h3.682c-.224.392-.462.812-.714 1.246H36.33v.924h3.458c-.308.476-.616.966-.952 1.456 1.162.266 2.324.574 3.486.924-1.26.49-3.15.882-5.642 1.176l.378.896c3.024-.406 5.208-.966 6.538-1.68a55.038 55.038 0 0 1 4.648 1.736l.63-.826a56.235 56.235 0 0 0-4.368-1.526c.742-.602 1.26-1.316 1.54-2.156h3.01v-.924h-7.574c.224-.392.462-.798.714-1.246h5.824v-3.528h-3.262v-1.246h4.13v-.91H36.512zm6.916 9.688a49.868 49.868 0 0 0-3.164-.798c.21-.308.434-.658.672-1.036h4.088c-.28.728-.812 1.344-1.596 1.834zm.364-7.532h-2.184v-1.246h2.184v1.246zm3.262 2.66h-2.296V17.16h2.296v1.778zm-3.262 0h-2.184V17.16h2.184v1.778zm-3.15 0h-2.296V17.16h2.296v1.778zm22.708-3.78h-3.276a18.26 18.26 0 0 0-.602-1.708l-1.022.168c.224.476.434.98.616 1.54h-3.22v2.814h.952v-1.904h5.586v1.848h.966v-2.758zm-4.9 1.792a32.85 32.85 0 0 1-.644 2.254H55.51v.966h1.96a20.284 20.284 0 0 1-1.022 2.226c.924.49 1.792.966 2.604 1.428-.952.7-2.338 1.26-4.186 1.68l.406.952c2.184-.518 3.752-1.204 4.732-2.072 1.26.742 2.31 1.414 3.15 2.03l.686-.798a38.204 38.204 0 0 0-3.178-1.946c.742-.924 1.232-2.1 1.456-3.5h1.68v-.966h-4.97a40.97 40.97 0 0 0 .602-2.17l-.98-.084zm2.702 3.22c-.238 1.232-.7 2.226-1.386 3.01-.658-.35-1.372-.714-2.128-1.106.294-.532.574-1.176.854-1.904h2.66zm-8.526 6.104c.798 0 1.204-.406 1.204-1.218V21.01c.434-.196.868-.392 1.302-.602v-1.022c-.434.224-.868.434-1.302.63v-2.8h1.316v-.966H53.83v-2.646h-1.036v2.646h-1.638v.966h1.638v3.206c-.616.224-1.26.42-1.918.574l.252 1.008a29.45 29.45 0 0 0 1.666-.574v3.374c0 .364-.182.546-.518.546s-.686-.028-1.05-.056l.21.98h1.19zM76.748 15.13l-.21 4.158h-2.576l.364-4.158h2.422zm-3.766 4.158h-1.778v.98h1.694L72.478 25h-1.694v.98h7.756V25h-1.26l.504-10.822h-6.216v.952h1.778l-.364 4.158zM73.444 25l.434-4.732h2.618L76.272 25h-2.828zm-5.908-11.41c-.392 1.68-1.022 3.206-1.89 4.578l.826.518c.49-.77.924-1.638 1.302-2.59h2.912v-.938H68.11c.14-.448.28-.896.406-1.372l-.98-.196zm-.42 4.382v.91h.882v1.722H66.08v.924h1.918v3.178c0 .196-.14.35-.42.462l.434.868c1.092-.322 2.072-.728 2.912-1.232l-.182-.896c-.588.378-1.176.686-1.75.924v-3.304h1.932v-.924h-1.932v-1.722h1.456v-.91h-3.332z' fill='%23fff'/%3E%3C/svg%3E"
    },
    onDragstart(event, item) {
      onDropSuccess = true;
      console.log('dragstart开始', event, item);
      event.dataTransfer.setData('componentData', JSON.stringify(item)) //在被拖拽对象的 dropstart 事件中传递消息
    },
    onDragEnd(event) {
      event.dataTransfer.clearData() //在被拖拽对象的 dragend 事件中清除消息
    },
    onDrop: async function (event) {
      if (!onDropSuccess) {
        return;
      }
      onDropSuccess = false;
      console.log('drop放置', event);
      let componentData = JSON.parse(event.dataTransfer.getData('componentData')) //在拖放区的 drop 事件中获取消息
      if (componentData) {
        const viewItem = await this.generateViewItem(componentData);
        if (viewItem) {
          let currentViewData = this.getCurrentViewData();
          currentViewData.viewItemList.push(viewItem);
        }
      }

    },
    onDropMainTable: async function (event) {
      if (!onDropSuccess) {
        return;
      }
      onDropSuccess = false;
      console.log('drop放置mainTable', event);
      let tdId = event.currentTarget.id;
      let tabId = event.currentTarget.getAttribute("p_table_id");
      let componentData = JSON.parse(event.dataTransfer.getData('componentData')) //在拖放区的 drop 事件中获取消息
      event.dataTransfer.setData('componentData', null);
      if (componentData.componentType === showType.field) {
        componentData['tableId'] = this.formData.formBean.mainTableBean.id;
        componentData['viewTableId'] = tdId;
        let field = await this.generateFormField(componentData);
        let viewItemBean = this.getViewItemBeanById(tabId);
        viewItemBean.refObj.tableContent[tdId] = field.dbFieldName;
      } else {
        this.$message.error('只能放置字段');
      }

    },
    getCurrentViewData() {
      return this.formData.formBean.viewBean;
    },
    async generateViewItem(componentData) {
      let tableViewItem = null;
      switch (componentData.componentType) {
        case showType.field:
          tableViewItem = await this.generateFieldView(componentData);
          break;
        case showType.mainTable:
          this.mainTableInitConfirmShow = true;
          break;
      }
      return tableViewItem;
    },
    generateMainTableView: function () {
      this.mainTableInitConfirmShow = false;
      let componentData = this.mainTableInitConfirmData;
      ContextApi.getNextId().then((nextId) => {
        let tableViewItem = {
          showType: showType.mainTable,
          refObj: {
            id: nextId,
            name: componentData.name,
            line: componentData.line,
            row: componentData.row,
            tableContent: {},
          }
        };
        for (let i = 0; i < tableViewItem.refObj.line; i++) {
          for (let j = 0; j < tableViewItem.refObj.row; j++) {
            tableViewItem.refObj.tableContent[this.getTableColId(tableViewItem, i, j)] = '';
          }
        }
        if (tableViewItem) {
          let currentViewData = this.getCurrentViewData();
          currentViewData.viewItemList.push(tableViewItem);
        }
      })

    },
    async generateFieldView(componentData) {
      componentData['tableId'] = this.formData.formBean.mainTableBean.id;
      let field = await this.generateFormField(componentData);
      return {
        showType: showType.field, // 字段
        refObj: {
          id: field.dbFieldName,
        }
      };
    },
    getTableColId(tableViewItem, lineNum, rowNum) {
      return 'tab' + tableViewItem.refObj.id + '_line' + lineNum + '_row' + rowNum;
    },
    loadFormDef() {
      this.formLoading = true;
      AppFormDesignApi.designBean(this.formData.formBean.id).then(resData => {
        resData.selectFormField = {};
        this.formData.formBean = resData;
        this.formLoading = false;
      })
    },
    mainTableDataInit(tableViewItem) {
      for (let i = 0; i < tableViewItem.line; i++) {
        for (let j = 0; j < tableViewItem.row; j++) {
          tableViewItem.tableData[this.getTableColId(tableViewItem, i, j)] = {};
        }
      }
    },
    selectField(fieldId) {
      for (const dbName in this.formData.formBean.fieldMap) {
        this.formData.formBean.fieldMap[dbName]['checked'] = false;
      }
      this.formData.formBean.fieldMap[fieldId]['checked'] = true;
      this.formData.formBean.selectFormField = this.formData.formBean.fieldMap[fieldId];
      this.activeKey = '2';
    },
    deleteFormField(fieldId) {
      fieldId.delete = true;
    },
    begin(e) {
      console.log('start:' + e);
    },
    getViewItemBeanById(itemId) {
      for (let i = 0; i < this.formData.formBean.viewBean.viewItemList.length; i++) {
        if (this.formData.formBean.viewBean.viewItemList[i].refObj.id === itemId) {
          return this.formData.formBean.viewBean.viewItemList[i];
        }
      }

    },
    async generateFormField(field) {
      let fieldLength = this.getFieldLength(field.type);
      field = {
        isNew: true,
        formId: this.formData.formBean.id,
        tableId: field.tableId,
        fieldName: field.name,
        dbFieldDataType: field.dbType,
        fieldDataType: field.type,
        length: fieldLength,
        width: 60,
        dbFieldName: '',
        span: 12
      };
      this.formLoading = true;
      await AppFormDesignApi.addField(field).then((res) => {
        field = res
        this.formData.formBean.fieldMap[field.dbFieldName] = field;
        this.formLoading = false;
      }).catch(res => {
        this.$message.error('添加字段出现异常:' + res);
      })
      return field
    },
    getFieldLength(fieldDataType) {
      let length = 36;
      if (fieldDataType === 'text') {
        length = 50;
      } else if (fieldDataType === 'counter') {
        length = 10;
      } else if (fieldDataType === 'radio') {
        length = 2;
      } else if (fieldDataType === 'date') {
        length = 8
      } else if (fieldDataType === 'file') {
        length = 36
      }
      return length;
    },
    formFieldAdd(evt) {
      window.console.log(evt);
    },
    formFieldChange(evt) {
      window.console.log(evt);
    },
    random() {
      return Math.random().toString(36).slice(-6);
    },
    async mergeBaseInfo() {
      this.formLoading = true;
      const that = this;
      await AppFormDesignApi.mergeBaseInfo(this.formData.formBean).then(res => {
        this.formLoading = false
      }).catch((res) => {
        that.$message.error('数据合并出现异常:' + res);
      })
    },
  }
}
</script>

<style scoped>

.field_components {
  background-color: #f5f5f5;
  text-align: center;
  padding: 5px;
  cursor: pointer;
}

.field_title {
  font-size: 10px;
}

.form_field {
  border: 1px dashed #bdbdbd;
  padding: 5px;
  margin-top: 7px;
  height: 60px;
  width: 100%;
}

.form_field_default {
  border: 3px solid #18aeff;
  margin-top: 5px;
}


.form_field_title {
  margin: 15px;
  width: 96%;
}

.form_field_checked {
  border: 3px solid #18aeff;
}

.select {
  background-color: #18aeff;
}

.form_item {
  width: 100vh;
  margin-top: 5px;
}

</style>
